package appmanager

import (
	"fmt"
	"io"
	"os"
	"path/filepath"

	"gitee.com/huoyu123hk/cloudAgent/pkg/logx"
	"gitee.com/huoyu123hk/cloudAgent/pkg/service"
)

type AppDeploy struct {
	Api       string `json:"api"`
	Token     string `json:"token"`
	Name      string `json:"name"`
	FileMd5   string `json:"fileMd5"`
	BackupDir string `json:"backupDir"`
	DeployDir string `json:"deployDir"`
}

func NewAppDeploy(api, token, name, fileMd5, backupDir, deployDir string) *AppDeploy {
	return &AppDeploy{
		Api:       api,
		Token:     token,
		Name:      name,
		FileMd5:   fileMd5,
		BackupDir: backupDir,
		DeployDir: deployDir,
	}
}

// Deploy 部署应用
func (ad *AppDeploy) Deploy() error {
	fileManager := NewFileManager(ad.Token, ad.Api)
	sourceFilePath := fileManager.Download(ad.FileMd5)
	fileName := filepath.Base(sourceFilePath)
	// 备份旧版本
	if ad.BackupDir != "" {
		if err := ad.backup(fileName); err != nil {
			logx.Errorf("备份失败: %v", err)
			return fmt.Errorf("备份失败: %v", err)
		}
	}
	logx.Infof("备份完成: %s", ad.BackupDir)
	// 部署新版本
	if _, err := os.Stat(ad.DeployDir); os.IsNotExist(err) {
		logx.Infof("部署目录不存在，创建: %s", ad.DeployDir)
		if err := os.MkdirAll(ad.DeployDir, 0755); err != nil {
			return fmt.Errorf("创建部署目录失败: %v", err)
		}
	}
	if err := ad.deploy(sourceFilePath); err != nil {
		logx.Errorf("部署失败: %v", err)
		return fmt.Errorf("部署失败: %v", err)
	}
	logx.Infof("部署完成: %s", ad.DeployDir)
	logx.Infof("开始重启服务: %s", ad.Name)
	// 重启服务
	serviceManager := service.NewServiceManager()
	if err := serviceManager.Restart(ad.Name); err != nil {
		logx.Errorf("服务重启失败: %v", err)
		return fmt.Errorf("服务重启失败: %v", err)
	}
	logx.Infof("服务重启完成: %s", ad.Name)
	return nil
}

// backup 备份旧版本
func (ad *AppDeploy) backup(name string) error {
	if ad.BackupDir == "" {
		return nil
	}

	logx.Infof("开始备份到目录: %s", ad.BackupDir)
	if _, err := os.Stat(ad.BackupDir); os.IsNotExist(err) {
		logx.Infof("备份目录不存在，创建: %s", ad.BackupDir)
		if err := os.MkdirAll(ad.BackupDir, 0755); err != nil {
			return fmt.Errorf("创建备份目录失败: %v", err)
		}
	}
	// 备份逻辑：复制当前部署目录到备份目录
	srcPath := filepath.Join(ad.DeployDir, name)
	backupPath := filepath.Join(ad.BackupDir, name)
	// 复制文件
	if err := Copy(srcPath, backupPath); err != nil {
		return fmt.Errorf("备份失败: %v", err)
	}
	logx.Infof("备份完成: %s", backupPath)
	return nil
}

// deploy 部署新版本
func (ad *AppDeploy) deploy(file string) error {
	fileName := filepath.Base(file)
	targetPath := filepath.Join(ad.DeployDir, fileName)
	return Copy(file, targetPath)
}

func Copy(src string, dst string) error {
	// 打开源文件
	sourceFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("打开源文件失败: %v", err)
	}
	defer sourceFile.Close()
	if _, err = os.Stat(dst); err == nil {
		os.Remove(dst)
	}
	// 创建目标文件
	destFile, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("创建目标文件失败: %v", err)
	}
	defer destFile.Close()

	// 复制文件内容
	if _, err := io.Copy(destFile, sourceFile); err != nil {
		return fmt.Errorf("复制文件内容失败: %v", err)
	}

	return nil
}
